import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _createSuper from "@babel/runtime/helpers/esm/createSuper";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _typeof from "@babel/runtime/helpers/esm/typeof";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
/*
 * @Descripttion:
 * @Author: gll
 * @Date: 2023-05-19 10:30:21
 * @LastEditors: gll
 * @LastEditTime: 2023-06-13 17:57:44
 */
import CryptoJS from 'crypto-js/crypto-js';
import { JSEncrypt } from 'encryptlong';
import { sm2, sm4 } from 'sm-crypto';
import { encodeBase64, decodeBase64 } from "./base64";

/** 对称加密, AES | SM4 */

/** 非对称加密, RSA | SM2 */
var AbstractEncrypt = /*#__PURE__*/function () {
  function AbstractEncrypt() {
    _classCallCheck(this, AbstractEncrypt);
  }
  _createClass(AbstractEncrypt, [{
    key: "pre",
    value: /** 将对象等形式的数据转换成字符串,是否开启base64转换解决中文乱码 */
    function pre(source, base64Format) {
      var data = source ? _typeof(source) === 'object' ? JSON.stringify(source) : source.toString() : source;
      return base64Format ? encodeBase64(data) : data;
    }
  }]);
  return AbstractEncrypt;
}();
/** AES加解密 */
var AES = /*#__PURE__*/function (_AbstractEncrypt) {
  _inherits(AES, _AbstractEncrypt);
  var _super = _createSuper(AES);
  function AES(key, iv) {
    var _this;
    _classCallCheck(this, AES);
    _this = _super.call(this);
    _defineProperty(_assertThisInitialized(_this), "key", void 0);
    _defineProperty(_assertThisInitialized(_this), "iv", void 0);
    _this.key = CryptoJS.enc.Utf8.parse(key);
    _this.iv = CryptoJS.enc.Utf8.parse(iv);
    return _this;
  }

  /**
   * @param key 秘钥
   */
  _createClass(AES, [{
    key: "setKey",
    value: function setKey(key) {
      this.key = CryptoJS.enc.Utf8.parse(key);
    }

    /**
     * @param key 偏移量
     */
  }, {
    key: "setIv",
    value: function setIv(iv) {
      this.iv = CryptoJS.enc.Utf8.parse(iv);
    }

    /**
     * AES加密
     * @param source
     * @returns
     */
  }, {
    key: "encrypt",
    value: function encrypt(source, options) {
      var word = this.pre(source);
      var _ref = options !== null && options !== void 0 ? options : {},
        _ref$mode = _ref.mode,
        mode = _ref$mode === void 0 ? 'ECB' : _ref$mode,
        _ref$padding = _ref.padding,
        padding = _ref$padding === void 0 ? 'Pkcs7' : _ref$padding;
      if (!this.key) throw new Error('AES key 未设置');
      if (mode !== 'ECB' && !this.iv) throw new Error('AES iv 未设置');
      var srcs = CryptoJS.enc.Utf8.parse(word);
      var ciphertext = CryptoJS.AES.encrypt(srcs, this.key, {
        iv: this.iv,
        mode: CryptoJS.mode[mode],
        padding: CryptoJS.pad[padding]
      });
      return ciphertext.toString();
    }

    /**
     * AES解密
     * @param source
     * @returns
     */
  }, {
    key: "decrypt",
    value: function decrypt(source, options) {
      var _ref2 = options !== null && options !== void 0 ? options : {},
        _ref2$mode = _ref2.mode,
        mode = _ref2$mode === void 0 ? 'ECB' : _ref2$mode,
        _ref2$padding = _ref2.padding,
        padding = _ref2$padding === void 0 ? 'Pkcs7' : _ref2$padding;
      if (!this.key) throw new Error('AES key 未设置');
      if (mode !== 'ECB' && !this.iv) throw new Error('AES iv 未设置');
      var decrypt = CryptoJS.AES.decrypt(source, this.key, {
        iv: this.iv,
        mode: CryptoJS.mode[mode],
        padding: CryptoJS.pad[padding]
      });
      return CryptoJS.enc.Utf8.stringify(decrypt).toString();
    }
  }]);
  return AES;
}(AbstractEncrypt);
/** RSA加解密 */
var RSA = /*#__PURE__*/function (_AbstractEncrypt2) {
  _inherits(RSA, _AbstractEncrypt2);
  var _super2 = _createSuper(RSA);
  function RSA(publicKey, privateKey) {
    var _this2;
    _classCallCheck(this, RSA);
    _this2 = _super2.call(this);
    _defineProperty(_assertThisInitialized(_this2), "publicKey", void 0);
    _defineProperty(_assertThisInitialized(_this2), "privateKey", void 0);
    _this2.publicKey = publicKey;
    _this2.privateKey = privateKey;
    return _this2;
  }

  /**
   * @param publicKey 公钥
   */
  _createClass(RSA, [{
    key: "setPublicKey",
    value: function setPublicKey(publicKey) {
      this.publicKey = publicKey;
    }

    /**
     * @param privateKey 私钥
     */
  }, {
    key: "setPrivateKey",
    value: function setPrivateKey(privateKey) {
      this.privateKey = privateKey;
    }

    /**
     * RSA加密
     * @param source
     * @param base64Format 是否需要进行base64转换
     * @returns
     */
  }, {
    key: "encrypt",
    value: function encrypt(source, base64Format) {
      var word = this.pre(source, base64Format);
      if (!this.publicKey) throw new Error('RSA publicKey 未设置');
      var encrypt = new JSEncrypt();
      encrypt.setPublicKey(this.publicKey);
      return encrypt.encryptLong(word);
    }

    /**
     * RSA解密
     * @param source
     * @param base64Format 解密完成后，是否再进行base64转换
     * @returns
     */
  }, {
    key: "decrypt",
    value: function decrypt(source, base64Format) {
      if (!this.privateKey) throw new Error('RSA privateKey 未设置');
      var decrypt = new JSEncrypt();
      decrypt.setPrivateKey(this.privateKey);
      return base64Format ? decodeBase64(decrypt.decryptLong(source)) : decrypt.decryptLong(source);
    }
  }]);
  return RSA;
}(AbstractEncrypt);
/** SM2加解密 */
var SM2 = /*#__PURE__*/function (_AbstractEncrypt3) {
  _inherits(SM2, _AbstractEncrypt3);
  var _super3 = _createSuper(SM2);
  function SM2(publicKey, privateKey) {
    var _this3;
    _classCallCheck(this, SM2);
    _this3 = _super3.call(this);
    _defineProperty(_assertThisInitialized(_this3), "publicKey", void 0);
    _defineProperty(_assertThisInitialized(_this3), "privateKey", void 0);
    _this3.publicKey = publicKey;
    _this3.privateKey = privateKey;
    return _this3;
  }

  /**
   * @param publicKey 公钥
   */
  _createClass(SM2, [{
    key: "setPublicKey",
    value: function setPublicKey(publicKey) {
      this.publicKey = publicKey;
    }

    /**
     * @param privateKey 私钥
     */
  }, {
    key: "setPrivateKey",
    value: function setPrivateKey(privateKey) {
      this.privateKey = privateKey;
    }

    /**
     * SM2加密
     * @param source
     * @param cipherMode 加密模式 1 - C1C3C2，0 - C1C2C3
     * @returns
     */
  }, {
    key: "encrypt",
    value: function encrypt(source) {
      var cipherMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
      var word = this.pre(source);
      if (!this.publicKey) throw new Error('SM2 publicKey 未设置');
      var encrypt = sm2.doEncrypt(word, this.publicKey, cipherMode);
      /** cipherMode为1时，加密密文拼接04，后端返回的密文也会以04开头 */
      return cipherMode === 1 ? "04".concat(encrypt) : encrypt;
    }

    /**
     * SM2解密
     * @param source
     * @param cipherMode 加密模式 1 - C1C3C2，0 - C1C2C3
     * @returns
     */
  }, {
    key: "decrypt",
    value: function decrypt(source) {
      var cipherMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
      /** cipherMode为1时需要截取掉04，再进行解密 */
      var word = cipherMode === 1 ? source === null || source === void 0 ? void 0 : source.slice(2) : source;
      if (!this.privateKey) throw new Error('SM2 privateKey 未设置');
      var decrypt = sm2.doDecrypt(word, this.privateKey, cipherMode);
      return decrypt;
    }
  }]);
  return SM2;
}(AbstractEncrypt);
/** SM4加解密 */
var SM4 = /*#__PURE__*/function (_AbstractEncrypt4) {
  _inherits(SM4, _AbstractEncrypt4);
  var _super4 = _createSuper(SM4);
  function SM4(key, iv) {
    var _this4;
    _classCallCheck(this, SM4);
    _this4 = _super4.call(this);
    _defineProperty(_assertThisInitialized(_this4), "key", void 0);
    _defineProperty(_assertThisInitialized(_this4), "iv", void 0);
    _this4.key = key;
    _this4.iv = iv;
    return _this4;
  }

  /**
   * @param key 秘钥
   */
  _createClass(SM4, [{
    key: "setKey",
    value: function setKey(key) {
      this.key = key;
    }

    /**
     * @param iv 偏移量
     */
  }, {
    key: "setIv",
    value: function setIv(iv) {
      this.iv = iv;
    }

    /**
     * SM4加密
     * @param source
     * @param options
     * @returns
     */
  }, {
    key: "encrypt",
    value: function encrypt(source, options) {
      var word = this.pre(source);
      var _ref3 = options !== null && options !== void 0 ? options : {},
        _ref3$mode = _ref3.mode,
        mode = _ref3$mode === void 0 ? 'ecb' : _ref3$mode,
        _ref3$padding = _ref3.padding,
        padding = _ref3$padding === void 0 ? 'pkcs#7' : _ref3$padding;
      if (!this.key) throw new Error('SM4 key 未设置');
      if (mode === 'cbc' && !this.iv) throw new Error('SM4 iv 未设置');
      var encrypt = sm4.encrypt(word, this.key, {
        iv: this.iv,
        mode: mode,
        padding: padding
      });
      return encrypt;
    }

    /**
     * SM4解密
     * @param source
     * @param options
     * @returns
     */
  }, {
    key: "decrypt",
    value: function decrypt(source, options) {
      var _ref4 = options !== null && options !== void 0 ? options : {},
        _ref4$mode = _ref4.mode,
        mode = _ref4$mode === void 0 ? 'ecb' : _ref4$mode,
        _ref4$padding = _ref4.padding,
        padding = _ref4$padding === void 0 ? 'pkcs#7' : _ref4$padding;
      if (!this.key) throw new Error('SM4 key 未设置');
      if (mode === 'cbc' && !this.iv) throw new Error('SM4 iv 未设置');
      var decrypt = sm4.decrypt(source, this.key, {
        iv: this.iv,
        mode: mode,
        padding: padding
      });
      return decrypt;
    }
  }]);
  return SM4;
}(AbstractEncrypt);
/** 加解密 */
export var crypto = function crypto(options) {
  var _ref5 = options !== null && options !== void 0 ? options : {},
    _ref5$type = _ref5.type,
    type = _ref5$type === void 0 ? 'AES' : _ref5$type;
  var crypto;
  switch (type) {
    case 'AES':
      crypto = new AES();
      break;
    case 'RSA':
      crypto = new RSA();
      break;
    case 'SM2':
      crypto = new SM2();
      break;
    case 'SM4':
      crypto = new SM4();
      break;
  }
  return crypto;
};